package com.kll.carolinehmibiz.base.utils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;

import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * NetworkUtil  网络管理工具
 *
 * @author Jack_Ou
 */
public class NetworkUtil {

    private static volatile NetworkUtil networkUtil;
    private static final String NETWORK_TYPE_NONE = "NETWORK_TYPE_NONE";

    private ConnectivityManager mManager;
    private TelephonyManager mTelephonyManager;
    private WifiManager mWifiManager;
    private WifiInfo mWifiInfo;

    /**
     * 构造函数私有化
     */
    private NetworkUtil() {
    }

    /**
     * 提供一个全局的静态方法
     *
     * @return NetworkUtil实例
     */
    public static NetworkUtil getInstance() {
        if (networkUtil == null) {
            synchronized (NetworkUtil.class) {
                if (networkUtil == null) {
                    networkUtil = new NetworkUtil();
                }
            }
        }
        return networkUtil;
    }

    public void setContext(Context context) {
        Context contextTemp = context.getApplicationContext();
        mManager = (ConnectivityManager) contextTemp.getSystemService(Context.CONNECTIVITY_SERVICE);
        mTelephonyManager = (TelephonyManager) contextTemp.getSystemService(Context.TELEPHONY_SERVICE);
        mWifiManager = (WifiManager) contextTemp.getSystemService(Context.WIFI_SERVICE);
    }

    /**
     * 检查网络是否可用
     *
     * @return true:网络可用   false：网络不可用
     */
    public boolean isNetworkAvailable() {
        if (null == mManager) {
            return false;
        }
        NetworkInfo info = mManager.getActiveNetworkInfo();
        return !(null == info || !info.isAvailable());
    }

    /**
     * 获取当前网络类型
     * <p>
     * NETWORK_TYPE_NONE  无网络
     * NETWORK_TYPE_WIFI  wifi网络
     * NETWORK_TYPE_4G    4G网络
     * NETWORK_TYPE_3G    3G网络
     * NETWORK_TYPE_2G    2G网络
     **/
    public String getNetworkType() {
        String netType = NETWORK_TYPE_NONE;
        //获取手机所有连接管理对象
        if (null == mManager) {
            return netType;
        }
        //获取NetworkInfo对象
        NetworkInfo networkInfo = null;
        networkInfo = mManager.getActiveNetworkInfo();
        //NetworkInfo对象为空 则代表没有网络
        if (networkInfo == null) {
            return netType;
        }
        //否则 NetworkInfo对象不为空 则获取该networkInfo的类型
        int nType = networkInfo.getType();
        if (nType == ConnectivityManager.TYPE_WIFI) {
            //WIFI
            netType = "NETWORK_TYPE_WIFI";
        } else if (nType == ConnectivityManager.TYPE_MOBILE) {
            netType = getInnerNetworkState(networkInfo.getSubtype());
        }
        return netType;
    }

    private String getInnerNetworkState(int nSubType) {
        String netType = NETWORK_TYPE_NONE;
        if (mTelephonyManager == null) {
            return netType;
        }
        if (nSubType == TelephonyManager.NETWORK_TYPE_LTE
                && !mTelephonyManager.isNetworkRoaming()) {
            //4G 网络
            netType = "NETWORK_TYPE_4G";
        } else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
                || nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
                || nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
                && !mTelephonyManager.isNetworkRoaming()) {
            //3G网络   联通的3G为UMTS或HSDPA 电信的3G为EVDO
            netType = "NETWORK_TYPE_3G";
        } else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
                || nSubType == TelephonyManager.NETWORK_TYPE_EDGE
                || nSubType == TelephonyManager.NETWORK_TYPE_CDMA
                && !mTelephonyManager.isNetworkRoaming()) {
            //2G网络 移动和联通的2G为GPRS或EGDE，电信的2G为CDMA
            netType = "NETWORK_TYPE_2G";
        } else {
            netType = NETWORK_TYPE_NONE;
        }
        return netType;
    }

    /**
     * 是否是wifi信号
     *
     * @return boolean true：是wifi信号    false：非wifi信号
     */
    public boolean isWifi() {
        if (null == mManager) {
            return false;
        }
        NetworkInfo activeNetInfo = mManager.getActiveNetworkInfo();
        return activeNetInfo != null
                && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
    }

    /**
     * 获取WIFI信息
     *
     * @return WifiInfo里面包含wifi信息
     */
    public WifiInfo fetchSSIDInfo() {
        if (mWifiManager == null) {
            return null;
        }
        mWifiInfo = mWifiManager.getConnectionInfo();
        return mWifiInfo;
    }

    /**
     * 获取WIFI名字
     *
     * @return WIFI名字
     */
    public String getWifiSSID() {
        mWifiInfo = fetchSSIDInfo();
        if (mWifiInfo == null) {
            return null;
        }
        return mWifiInfo.getSSID().replace("\"", "");
    }

    /**
     * 获取WIFi的BSSID
     *
     * @return BSSID
     */
    public String getWifiBSSID() {
        mWifiInfo = fetchSSIDInfo();
        if (mWifiInfo == null) {
            return null;
        }
        return mWifiInfo.getBSSID();
    }

    /**
     * 获取WIFi的MAC地址
     *
     * @return mac地址
     */
    public String getWifiMacAddress() {
        mWifiInfo = fetchSSIDInfo();
        if (mWifiInfo == null) {
            return null;
        }
        return mWifiInfo.getMacAddress();
    }

    /**
     * 获取Wifi信号强度
     * 0到-100的区间值
     * 0到-50表示信号最好
     * -50到-70表示信号偏差
     * 小于-70表示最差
     *
     * @return wifi信号强度
     **/
    public int getWifiSignalStrength() {
        mWifiInfo = fetchSSIDInfo();
        if (mWifiInfo == null) {
            return -1;
        }
        return fetchSSIDInfo().getRssi();
    }

    /**
     * 获取WI-FI设备IP地址
     *
     * @return ip地址
     **/
    public String getIPAddress() {
        mWifiInfo = fetchSSIDInfo();
        if (mWifiInfo == null) {
            return null;
        }
        return getCorrectIPAddress(fetchSSIDInfo().getIpAddress());
    }

    /**
     * 获取开启热点时设备IP地址
     *
     * @return 获得开启热点时的IP地址
     **/
    public String getServerAddress() {
        if (mWifiManager == null) {
            return "";
        }
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }
        DhcpInfo dhcpinfo = mWifiManager.getDhcpInfo();
        return getCorrectIPAddress(dhcpinfo.serverAddress);
    }

    /**
     * 获取WIFI热点的状态
     *
     * @return 热点状态枚举
     **/
    public HOTSPOT getWifiApState() {
        if (mWifiManager == null) {
            return null;
        }
        try {
            Method method = mWifiManager.getClass().getMethod("getWifiApState");
            if (method == null) {
                return null;
            }
            return HOTSPOT.getType((int) method.invoke(mWifiManager));
        } catch (Exception e) {
            return HOTSPOT.WIFI_AP_STATE_FAILED;
        }
    }

    /**
     * 判断Wifi热点是否可用
     **/
    public boolean isApEnabled() {
        return (getWifiApState() == HOTSPOT.WIFI_AP_STATE_ENABLED);
    }

    /**
     * 获取连接到当前热点的设备IP
     **/
    public List<String> getConnectedHotIP() {
        ArrayList<String> connectedIP = new ArrayList<>();
        try (
                FileReader fr = new FileReader("/proc/net/arp");
                BufferedReader br = new BufferedReader(fr)
        ) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] splitted = line.split(" +");
                if (splitted.length >= 4) {
                    String ip = splitted[0];
                    connectedIP.add(ip);
                }
            }
        } catch (Exception e) {
//            LogUtils.e(e);
            e.printStackTrace();
        }
        connectedIP.remove(0);
        return connectedIP;
    }

    /**
     * 将获取的int转为真正的ip地址
     **/
    private String getCorrectIPAddress(int iPAddress) {
        StringBuilder sb = new StringBuilder();
        sb.append(iPAddress & 0xFF).append(".");
        sb.append((iPAddress >> 8) & 0xFF).append(".");
        sb.append((iPAddress >> 16) & 0xFF).append(".");
        sb.append((iPAddress >> 24) & 0xFF);
        return sb.toString();
    }
}
